<?php
// +----------------------------------------------------------------------
// | 易联云云打印
// +----------------------------------------------------------------------

use think\facade\Cache;

class Printer
{
    private $host = 'https://open-api.10ss.net';

    private $client_id;

    private $client_secret;

    private $access_token;

    public function __construct($config)
    {
        $this->client_id     = $config['client_id'];
        $this->client_secret = $config['client_secret'];
        $this->access_token  = $this->setAccessToken();
    }

    private function setAccessToken()
    {
        $key = 'token:printer';
        if (!Cache::store('redis')->has($key)) {
            $response = $this->accessToken();
            Cache::store('redis')->set($key, $response['body']['access_token'], $response['body']['expires_in']);
        }
        return Cache::store('redis')->get($key);
    }

    /**
     * 获取Access Token
     */
    public function accessToken(): array
    {
        $url = $this->host . '/oauth/oauth';
        $timestamp = time();
        $params = [
            'client_id'  => $this->client_id,
            'grant_type' => 'client_credentials',
            'sign'       => $this->getSign($timestamp),
            'scope'      => 'all',
            'timestamp'  => $timestamp,
            'id'         => $this->uuid4()
        ];
        return $this->request($url, $params);
    }

    /**
     * 更新Access Token
     */
    public function refreshToken($refresh_token): array
    {
        $url = $this->host . '/oauth/oauth';
        $timestamp = time();
        $params = [
            'client_id'     => $this->client_id,
            'grant_type'    => 'refresh_token',
            'sign'          => $this->getSign($timestamp),
            'scope'         => 'all',
            'refresh_token' => $refresh_token,
            'timestamp'     => $timestamp,
            'id'            => $this->uuid4()
        ];
        return $this->request($url, $params);
    }

    /**
     * 终端授权 (永久授权)
     * @param $machine_code
     * @param $msign
     * @return array
     */
    public function addPrinter($machine_code, $msign): array
    {
        $url = $this->host . '/printer/addprinter';
        $timestamp = time();
        $params = [
            'client_id'    => $this->client_id,
            'machine_code' => $machine_code,
            'msign'        => $msign,
            'access_token' => $this->access_token,
            'sign'         => $this->getSign($timestamp),
            'id'           => $this->uuid4(),
            'timestamp'    => $timestamp,
        ];
        return $this->request($url, $params);
    }

    /**
     * 文本打印
     * @param string $machine_code
     * @param string $order_sn
     * @param string $content
     * @return array
     */
    public function print($machine_code, $order_sn, $content)
    {
        $url = $this->host . '/print/index';
        $timestamp = time();
        $params = [
            'client_id'    => $this->client_id,
            'access_token' => $this->access_token,
            'machine_code' => $machine_code,
            'content'      => $content,
            'origin_id'    => $order_sn,
            'sign'         => $this->getSign($timestamp),
            'id'           => $this->uuid4(),
            'timestamp'    => $timestamp,
        ];
        return $this->request($url, $params);
    }
    
    /**
     * 签名
     * @param int $timestamp
     * @return string
     */
    private function getSign(int $timestamp): string
    {
        return strtolower(md5($this->client_id . $timestamp . $this->client_secret));
    }

    /**
     * uuid4
     * 标准的UUID格式为：xxxxxxxx-xxxx-xxxx-xxxxxx-xxxxxxxxxx(8-4-4-4-12)
     */
    private function uuid4(): string
    {
        $chars = md5(uniqid(mt_rand(), true));
        $str = substr ( $chars, 0, 8 ) . '-'
            . substr ( $chars, 8, 4 ) . '-'
            . substr ( $chars, 12, 4 ) . '-'
            . substr ( $chars, 16, 4 ) . '-'
            . substr ( $chars, 20, 12 );
        return strtoupper($str);
    }

    /**
     * 发送请求
     * @param string $url
     * @param array $params
     * @return array
     */
    public function request(string $url, array $params): array
    {
        $client = new \GuzzleHttp\Client();
        $response = $client->request('POST', $url, [
            'form_params' => $params,
            'headers'=>['Content-Type' => 'application/x-www-form-urlencoded']
        ]);
        return json_decode($response->getBody(), true);
    }
}